package com.midea.trade.sharding.druid.route;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import com.midea.trade.sharding.config.Configurations;



public class RouteResultset {
	
	 private String statement; // 原始语句
	    
	    private final int sqlType;
	    
	    private RouteResultsetNode[] nodes; // 路由结果节点

	    private int limitStart;
	    
	    private boolean cacheAble;
	    // used to store table's ID->datanodes cache
	    // format is table.primaryKey
	    private String primaryKey;
	    // limit output total
	    private int limitSize;
	    private SQLMerge sqlMerge;

	    private boolean callStatement = false; // 处理call关键字

	    // 是否为全局表，只有在insert、update、delete、ddl里会判断并修改。默认不是全局表，用于修正全局表修改数据的反馈。
	    private boolean globalTableFlag = false;

	    //是否完成了路由
	    private boolean isFinishedRoute = false;

	    //是否自动提交，此属性主要用于记录ServerConnection上的autocommit状态
	    private boolean autocommit = true;

	    private boolean isLoadData=false;

	    //是否可以在从库运行,此属性主要供RouteResultsetNode获取
	    private Boolean canRunInReadDB;

	    public boolean isLoadData()
	    {
	        return isLoadData;
	    }

	    public void setLoadData(boolean isLoadData)
	    {
	        this.isLoadData = isLoadData;
	    }

	    public boolean isFinishedRoute() {
	        return isFinishedRoute;
	    }

	    public void setFinishedRoute(boolean isFinishedRoute) {
	        this.isFinishedRoute = isFinishedRoute;
	    }

	    public boolean isGlobalTable() {
	        return globalTableFlag;
	    }

	    public void setGlobalTable(boolean globalTableFlag) {
	        this.globalTableFlag = globalTableFlag;
	    }

	    public RouteResultset(String stmt, int sqlType) {
	        this.statement = stmt;
	        this.limitSize = -1;
	        this.sqlType = sqlType;
	    }

	    public void resetNodes() {
	        if (nodes != null) {
	            for (RouteResultsetNode node : nodes) {
	                node.resetStatement();
	            }
	        }
	    }

	    public void copyLimitToNodes() {

	        if(nodes!=null)
	        {
	            for (RouteResultsetNode node : nodes)
	            {
	                if(node.getLimitSize()==-1&&node.getLimitStart()==0)
	                {
	                    node.setLimitStart(limitStart);
	                    node.setLimitSize(limitSize);
	                }
	            }

	        }
	    }


	    public SQLMerge getSqlMerge() {
	        return sqlMerge;
	    }

	    public boolean isCacheAble() {
	        return cacheAble;
	    }

	    public void setCacheAble(boolean cacheAble) {
	        this.cacheAble = cacheAble;
	    }

	    public boolean needMerge() {
	        return limitSize > 0 || sqlMerge != null;
	    }

	    public int getSqlType() {
	        return sqlType;
	    }

	    public boolean isHasAggrColumn() {
	        return (sqlMerge != null) && sqlMerge.isHasAggrColumn();
	    }

	    public int getLimitStart() {
	        return limitStart;
	    }

	    public String[] getGroupByCols() {
	        return (sqlMerge != null) ? sqlMerge.getGroupByCols() : null;
	    }

	    private SQLMerge createSQLMergeIfNull() {
	        if (sqlMerge == null) {
	            sqlMerge = new SQLMerge();
	        }
	        return sqlMerge;
	    }

	    public Map<String, Integer> getMergeCols() {
	        return (sqlMerge != null) ? sqlMerge.getMergeCols() : null;
	    }

	    public void setLimitStart(int limitStart) {
	        this.limitStart = limitStart;
	    }

	    public String getPrimaryKey() {
	        return primaryKey;
	    }

	    public boolean hasPrimaryKeyToCache() {
	        return primaryKey != null;
	    }

	    public void setPrimaryKey(String primaryKey) {
	        if (!primaryKey.contains(".")) {
	            throw new java.lang.IllegalArgumentException(
	                    "must be table.primarykey fomat :" + primaryKey);
	        }
	        this.primaryKey = primaryKey;
	    }

	    /**
	     * return primary key items ,first is table name ,seconds is primary key
	     *
	     * @return
	     */
	    public String[] getPrimaryKeyItems() {
	        return primaryKey.split("\\.");
	    }

	    public void setOrderByCols(LinkedHashMap<String, Integer> orderByCols) {
	        if (orderByCols != null && !orderByCols.isEmpty()) {
	            createSQLMergeIfNull().setOrderByCols(orderByCols);
	        }
	    }

	    public void setHasAggrColumn(boolean hasAggrColumn) {
	        if (hasAggrColumn) {
	            createSQLMergeIfNull().setHasAggrColumn(true);
	        }
	    }

	    public void setGroupByCols(String[] groupByCols) {
	        if (groupByCols != null && groupByCols.length > 0) {
	            createSQLMergeIfNull().setGroupByCols(groupByCols);
	        }
	    }

	    public void setMergeCols(Map<String, Integer> mergeCols) {
	        if (mergeCols != null && !mergeCols.isEmpty()) {
	            createSQLMergeIfNull().setMergeCols(mergeCols);
	        }

	    }

	    public LinkedHashMap<String, Integer> getOrderByCols() {
	        return (sqlMerge != null) ? sqlMerge.getOrderByCols() : null;

	    }

	    public String getStatement() {
	        return statement;
	    }

	    public RouteResultsetNode[] getNodes() {
	        return nodes;
	    }

	    public void setNodes(RouteResultsetNode[] nodes) {
	        if(nodes!=null)
	        {
	           int nodeSize=nodes.length;
	            for (RouteResultsetNode node : nodes)
	            {
	                node.setTotalNodeSize(nodeSize);
	            }

	        }
	        this.nodes = nodes;
	    }

	    /**
	     * @return -1 if no limit
	     */
	    public int getLimitSize() {
	        return limitSize;
	    }

	    public void setLimitSize(int limitSize) {
	        this.limitSize = limitSize;
	    }

	    public void setStatement(String statement) {
	        this.statement = statement;
	    }

	    public boolean isCallStatement() {
	        return callStatement;
	    }

	    public void setCallStatement(boolean callStatement) {
	        this.callStatement = callStatement;
	    }

	    public void changeNodeSqlAfterAddLimit(Configurations configurations, String sourceDbType, String sql, int offset, int count, boolean isNeedConvert) {
	       /* if (nodes != null) {

	            Map<String, String> dataNodeDbTypeMap = schemaConfig.getDataNodeDbTypeMap();
	            Map<String, String> sqlMapCache = new HashMap<>();
	            for (RouteResultsetNode node : nodes)
	            {
	                String dbType = dataNodeDbTypeMap.get(node.getName());
	                if (sourceDbType.equalsIgnoreCase("mysql"))
	                {
	                    node.setStatement(sql);   //mysql之前已经加好limit
	                } else if (sqlMapCache.containsKey(dbType))
	                {
	                    node.setStatement(sqlMapCache.get(dbType));
	                } else if(isNeedConvert)
	                {
	                    String nativeSql = PageSQLUtil.convertLimitToNativePageSql(dbType, sql, offset, count);
	                    sqlMapCache.put(dbType, nativeSql);
	                    node.setStatement(nativeSql);
	                }  else {
	                    node.setStatement(sql);
	                }

	                node.setLimitStart(offset);
	                node.setLimitSize(count);
	            }


	        }*/
	    }

	    public boolean isAutocommit() {
	        return autocommit;
	    }

	    public void setAutocommit(boolean autocommit) {
	        this.autocommit = autocommit;
	    }

	    public Boolean getCanRunInReadDB() {
	        return canRunInReadDB;
	    }

	    public void setCanRunInReadDB(Boolean canRunInReadDB) {
	        this.canRunInReadDB = canRunInReadDB;
	    }

		public HavingCols getHavingCols() {
			return (sqlMerge != null) ? sqlMerge.getHavingCols() : null;
		}

		public void setHavings(HavingCols havings) {
			if (havings != null) {
				createSQLMergeIfNull().setHavingCols(havings);
			}
		}

	   


}
